<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>02_显式原型与隐式原型</title>
</head>
<body>
<!--
1. 每个函数都有一个prototype,即显式原型,它默认指向一个Object空对象
2. 每个实例对象都有一个__proto__,即隐式原型,它默认指向一个Object空对象
3. 实例对象的隐式原型的值,为其对应构造函数的显式原型的值
4. 内存结构(图)
5. 总结:
  * 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个Object空对象
  * 实例对象的__proto__属性: 创建对象时自动添加, 默认指向构造函数的prototype
  * 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前)
-->
<script type="text/javascript">
    // 每个函数都有一个prototype,即显式原型,它默认指向一个Object空对象
    function Fn() {} //创建函数对象的内部语句：this.prototype={}

    // 函数对象创建之后才有prototype属性
    console.log(Fn.prototype)

    // 每个实例对象都有一个__proto__,即隐式原型,它默认指向一个Object空对象
    var fn = new Fn()//创建实例对象的内部语句：this.__proto__=Fn.prototype

    console.log(fn.prototype)//undefined 实例没有prototype属性
    // 实例对象创建之后才有__proto__属性
    console.log(fn.__proto__)
    // 对象隐式原型的值为其对应的构造函数的显式原型的值
    console.log(fn.__proto__ === Fn.prototype)//true

    Fn.prototype.test = function () {
        console.log('test()')
    }
    // Fn.test() //Fn.test is not a function 显示原型的属性和方法仅供实例使用
    fn.test()  //


    // function Fn(name) {
    //     this.name = name
    // }
    //
    // function newCopy(args) {
    //     const obj = {}
    //     obj.__proto__ = Fn.prototype
    //     Fn.call(obj, args)
    //     return obj
    // }
    //
    // const c1 = new Fn('tom')
    // const c2 = newCopy('独孤求败', '')
    // console.log(c1);
    // console.log(c2);
    // console.log(c1 === c2);

</script>
</body>
</html>
